package com.corpgovernment.organization.service.impl;

import com.corpgovernment.api.basic.vo.UserLoginResponseVo;
import com.corpgovernment.api.organization.enums.LoginTypeEnum;
import com.corpgovernment.api.organization.model.user.login.MbUserLoginVo;
import com.corpgovernment.common.base.BaseUserInfo;
import com.corpgovernment.common.base.CommonException;
import com.corpgovernment.common.common.CorpBusinessException;
import com.corpgovernment.organization.constant.OrganizationResponseCodeEnum;
import com.corpgovernment.organization.dataloader.db.MbUserLoginLoader;
import com.corpgovernment.organization.entity.db.MbUserLogin;
import com.corpgovernment.organization.factory.LoginSourceServiceFactory;
import com.ctrip.corp.obt.auth.client.handler.token.JwtTokenHandler;
import com.ctrip.corp.obt.auth.core.token.OAuth2AccessToken;
import com.ctrip.corp.obt.generic.core.context.TenantContext;
import com.ctrip.corp.obt.generic.utils.ExceptionUtils;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import static com.corpgovernment.api.basic.metadata.ELoginStatus.ACCOUNT_DISABLED;

/**
 * @author jhxue
 * @create 2022-02-18-14:22
 */
@Slf4j
@Service
public class SmsLoginService extends AbstractLoginService {

	private static final Integer MSG_CODE_LENGTH = 6;

	private static final String CODE_MODE_SMS = "SMS";
	private static final String PARAM_NAME_SOURCE = "source";
	private static final String PARAM_NAME_MOBILE = "mobile";
	private static final String PARAM_NAME_COUNTRY_CODE = "countryCode";

	@Autowired
	private MbUserLoginLoader mbUserLoginLoader;
	@Autowired
	private JwtTokenHandler jwtTokenHandler;
	@Autowired
	private LoginSourceServiceFactory loginSourceServiceFactory;


	@Override
	public UserLoginResponseVo login(MbUserLoginVo request) {

		//验证参数
		String msgCode = request.getMsgCode();
		if (msgCode.length() != MSG_CODE_LENGTH) {
			throw new CorpBusinessException(OrganizationResponseCodeEnum.VERIFICATION_CODE_LENGTH_ERROR);
		}

		String phoneNum = request.getPhoneNum();
		if (!Pattern.matches("^1[3-9]\\d{9}$", phoneNum)) {
			throw new CorpBusinessException(OrganizationResponseCodeEnum.PHONE_NUM_INCORRECT_FORMAT);
		}

		String countryCode = request.getCountryCode();
		MbUserLogin mbUserLogin = this.getByPhoneNumAndCountryCodeAndBgUser(phoneNum, countryCode);
		if (mbUserLogin == null) {
			throw new CorpBusinessException(OrganizationResponseCodeEnum.CUSTOM_CONTENT, "您输入的手机号未注册，请重新输入");
		}
		// 账号是否被禁用
		boolean isEnable = mbUserLogin.getStatus() == 1;
		if (!isEnable) {
			throw new CorpBusinessException(OrganizationResponseCodeEnum.CUSTOM_CONTENT, ACCOUNT_DISABLED.getDesc());
		}

		String clientId = TenantContext.getClientId();
		Map<String, String> systemParams = new HashMap<>(4);
		systemParams.put(PARAM_NAME_SOURCE, request.getSource());
		systemParams.put(PARAM_NAME_MOBILE, request.getPhoneNum());
		systemParams.put(PARAM_NAME_COUNTRY_CODE, request.getCountryCode());

		OAuth2AccessToken oAuth2AccessToken = ExceptionUtils.catchThrow(
				() -> jwtTokenHandler.createAccessTokenInAuthCodeMode(
						clientId, msgCode, CODE_MODE_SMS, false, systemParams),
				exception -> {
					log.error("createAccessTokenInAuthCodeMode exception: " + exception.getMessage(), exception);
					throw new CommonException(exception.getMessage());
				});
		log.info("create access token info:{} in sms code mode ", JsonUtils.toJsonString(oAuth2AccessToken));

		Map<String, Object> userInfoByAccessToken = ExceptionUtils.catchThrow(
				() -> jwtTokenHandler.getUserInfoByAccessToken(clientId, oAuth2AccessToken.getValue()),
				exception -> {
					log.error("getUserInfoByAccessToken exception: " + exception.getMessage(), exception);
					throw new CommonException(exception.getMessage());
				});
		BaseUserInfo userInfo = JsonUtils.convert(userInfoByAccessToken, BaseUserInfo.class);
		userInfo.setToken((String) userInfoByAccessToken.get("id"));
		UserLoginResponseVo response = new UserLoginResponseVo();
		response.setToken(oAuth2AccessToken.getValue())
				.setUserName(userInfo.getUserName())
				.setUid(userInfo.getUid())
				.setAccountName(userInfo.getAccountName())
				.setBgUser(userInfo.getBgUser())
				.setSource(userInfo.getSource())
				.setCid((String) userInfoByAccessToken.get("cid"))
				.setShowManage(false)
				.setRefreshToken(oAuth2AccessToken.getRefreshToken().getValue())
				.setExpiration(oAuth2AccessToken.getExpiration());
		return loginSourceServiceFactory.getLoginSourceService(request.getSource()).process(userInfo, response, LoginTypeEnum.SMS);
	}

	private MbUserLogin getByPhoneNumAndCountryCodeAndBgUser(String phoneNum, String countryCode) {
		MbUserLogin queryParam = new MbUserLogin();
		queryParam.setPhoneNum(phoneNum);
		queryParam.setCountryCode(countryCode);
		queryParam.setBgUser(0);
		return mbUserLoginLoader.selectOneByRecord(queryParam);
	}

	@Override
	public String getLoginType() {
        return LoginTypeEnum.SMS.toString();
    }
}
